home *** CD-ROM | disk | FTP | other *** search
- {From: "Carl O" <cro@br213mail.nrel.gov>}
- {Subject: Mac Serial I/O code}
- {}
- {Attached is my Mac serial code. The program is a complete simple terminal}
- {emulator that used some popup menu buttons that I was experimenting with.}
- {You can just trash those if you like--the actual serial port code is what}
- {I think you are interested in. Any questions, just ask.}
- {}
- {Carl R. Osterwald}
-
- {Changes by Ingemar Ragnemalm:}
- {Changed RamSDOpen/RamSDClose to OpenDriver/CloseDriver.}
- {Removed or commented out some stuff that don't apply to Think Pascal.}
- {Changed some identifiers to get closer to the Mac standard.}
- {Added some minor GUI features like Apple menu and About box.}
-
- program Term;
-
- uses
- {$IFC UNDEFINED THINK_PASCAL}
- {Change these to, for example, MPW interfaces.}
- MemTypes, QuickDraw, OSIntf, ToolIntf, PackIntf, OSErrTrap,
- {$ENDC}
- Serial;
-
- type
- Pac2 = packed array[1..2] of char;
- Pac64 = packed array[1..64] of char;
-
- const
- kChanARcvAvail = 24;
- menu_ID = 1;
- aboutID = 128;
- appleMenu_ID = 2;
- baud_menu_ID = 235;
- parity_menu_ID = 234;
- quit_item = 1;
- about_item = 1;
- baud_300_item = 1;
- baud_600_item = 2;
- baud_1200_item = 3;
- baud_1800_item = 4;
- baud_2400_item = 5;
- baud_3600_item = 6;
- baud_4800_item = 7;
- baud_7200_item = 8;
- baud_9600_item = 9;
- baud_19200_item = 10;
- baud_57600_item = 11;
- no_parity_item = 1;
- even_parity_item = 2;
- odd_parity_item = 3;
- scroll_bar_width = 16;
- indent = 4;
- line_space = 11;
- char_space = 6;
- ascent = 9;
- descent = 2;
- loop_length = 16;
- flash_interval = $00000010;
- control_G = $07;
- control_H = $08;
- control_J = $0A;
- control_M = $0D;
-
- var
- appleMenu, menu: MenuHandle;
- baud_menu: MenuHandle;
- parity_menu: MenuHandle;
- menu_choice: LongInt;
- baud: integer;
- parity: integer;
- checked_baud: integer;
- checked_parity: integer;
- window_rectangle: Rect;
- terminal_window: WindowPtr;
- terminal_rectangle: Rect;
- temp_rectangle: Rect;
- temp_control: ControlHandle;
- break_button: ControlHandle;
- help_button: ControlHandle;
- update_region: RgnHandle;
- which_window: WindowPtr;
- which_control: ControlHandle;
- click_location: Point;
- current_event: EventRecord;
- finished: boolean;
- cursor_visible: Boolean;
- cursor_rectangle: Rect;
- next_flash_time: LongInt;
- xPos: integer;
- yPos: integer;
- received_char: char;
- buffer_ptr: Ptr;
- in_buffer: Pac64;
- this_char: Pac2;
- screen_line: string[80];
- width: integer;
- height: integer;
- right_limit: integer;
- bottom_limit: integer;
- no_of_lines: integer;
- index: integer;
- limit: integer;
- len: integer;
- configuration_word: integer;
- protocol_record: SerShk;
- byte_count: LongInt;
- num_string: Str255;
-
- {--------------------------------------------------------------------------}
-
- procedure ErrorHandler (theErr: OSErr);
- begin
- if theErr = noErr then
- exit(ErrorHandler);
- SysBeep(10);
- ExitToShell; {Eller halt?}
- end;
-
- {--------------------------------------------------------------------------}
-
- procedure ConfigureModemPort;
-
- begin { ConfigureModemPort }
- case checked_baud of
- baud_300_item:
- baud := baud300;
- baud_600_item:
- baud := baud600;
- baud_1200_item:
- baud := baud1200;
- baud_1800_item:
- baud := baud1800;
- baud_2400_item:
- baud := baud2400;
- baud_3600_item:
- baud := baud3600;
- baud_4800_item:
- baud := baud4800;
- baud_7200_item:
- baud := baud7200;
- baud_9600_item:
- baud := baud9600;
- baud_19200_item:
- baud := baud19200;
- baud_57600_item:
- baud := baud57600;
- otherwise
- baud := baud1200;
- end; { case }
- case checked_parity of
- no_parity_item:
- parity := noParity;
- even_parity_item:
- parity := evenParity;
- odd_parity_item:
- parity := oddParity;
- otherwise
- parity := evenParity;
- end; { case }
- configuration_word := BitOr(BitOr(baud, data7), BitOr(parity, stop10));
- ErrorHandler(SerReset(aInRefNum, configuration_word));
- ErrorHandler(SerReset(aOutRefNum, configuration_word));
- CheckItem(baud_menu, checked_baud, true);
- CheckItem(parity_menu, checked_parity, true);
- end; { ConfigureModemPort }
-
- {--------------------------------------------------------------------------}
-
- procedure ControlActionProcedure (which_control: ControlHandle; part_code: integer);
- var
- which_menu: integer;
- which_item: integer;
- menu_point: Point;
- menu_width: integer;
-
- begin { ControlActionProcedure }
- HLock(Handle(which_control));
- with which_control^^ do
- begin
- InsertMenu(MenuHandle(contrlRfCon), -1);
- CalcMenuSize(MenuHandle(contrlRfCon));
- menu_point.v := contrlRect.top;
- menu_point.h := contrlRect.left;
- LocalToGlobal(menu_point);
- menu_width := MenuHandle(contrlRfCon)^^.menuWidth + 2;
- with menu_point do
- menu_choice := PopUpMenuSelect(MenuHandle(contrlRfCon), v - 1, h - menu_width, contrlMax);
- DeleteMenu(contrlMin);
- which_menu := HiWord(menu_choice);
- which_item := LoWord(menu_choice);
- case which_menu of
- baud_menu_ID:
- begin
- CheckItem(baud_menu, contrlValue, false);
- case which_item of
- baud_300_item:
- baud := baud300;
- baud_600_item:
- baud := baud600;
- baud_1200_item:
- baud := baud1200;
- baud_1800_item:
- baud := baud1800;
- baud_2400_item:
- baud := baud2400;
- baud_3600_item:
- baud := baud3600;
- baud_4800_item:
- baud := baud4800;
- baud_7200_item:
- baud := baud7200;
- baud_9600_item:
- baud := baud9600;
- baud_19200_item:
- baud := baud19200;
- baud_57600_item:
- baud := baud57600;
- otherwise
- which_item := contrlValue;
- end; { case }
- CheckItem(baud_menu, which_item, true);
- checked_baud := which_item;
- ContrlValue := which_item;
- ConfigureModemPort;
- end;
- parity_menu_ID:
- begin
- CheckItem(parity_menu, contrlValue, false);
- case which_item of
- no_parity_item:
- parity := noParity;
- even_parity_item:
- parity := evenParity;
- odd_parity_item:
- parity := oddParity;
- otherwise
- which_item := contrlValue;
- end; { case }
- CheckItem(parity_menu, which_item, true);
- checked_parity := which_item;
- ContrlValue := which_item;
- ConfigureModemPort;
- end;
- end; { case }
- end; { with }
- HLock(Handle(which_control));
- end; { ControlActionProcedure }
-
- {--------------------------------------------------------------------------}
-
- {procedure RamSDOpen (whichPort: SPortSel): OSErr;}
-
- procedure InitializeModemPort;
-
- var
- aInRefNumDummy, aOutRefNumDummy: integer;
- begin { InitializeModemPort }
- {RamSDOpen changed to OpenDriver}
- {ErrorHandler(RamSDOpen(SPortA)); { open driver for modem port }
-
- { A = modem port, B = printer port}
- ErrorHandler(OpenDriver('.AIn', aInRefNumDummy));
- ErrorHandler(OpenDriver('.AOut', aOutRefNumDummy));
-
- ConfigureModemPort;
- with protocol_record do
- begin
- fXon := 0; { Xon/Xoff for output disabled }
- fCTS := 0; { CTS handshake disabled }
- errs := 0; { don't bother with errors }
- evts := 0; { don't post status events }
- fInX := 0; { Xon/Xoff for input disabled }
- end; { with }
- ErrorHandler(SerHShake(aInRefNum, protocol_record));
- ErrorHandler(SerHShake(aOutRefNum, protocol_record));
- this_char[1] := ' ';
- end; { InitializeModemPort }
-
- {--------------------------------------------------------------------------}
-
- procedure InitializeUserInterface;
-
- begin { intialize_user_interface }
- {$IFC UNDEFINED THINK_PASCAL}
- InitGraf(@thePort);
- InitFonts;
- InitWindows;
- InitMenus;
- TEInit;
- InitDialogs(nil);
- {$ENDC}
- FlushEvents(everyEvent, 0);
-
- appleMenu := NewMenu(appleMenu_ID, concat(char($14)));
- AppendMenu(appleMenu, 'About Term…;(-');
- AddResMenu(appleMenu, 'DRVR');
- InsertMenu(appleMenu, 0);
-
- menu := NewMenu(menu_ID, 'File');
- AppendMenu(menu, 'Quit/Q');
- InsertMenu(menu, 0);
- baud_menu := NewMenu(baud_menu_ID, 'Baud');
- AppendMenu(baud_menu, '300;600;1200;1800;2400;3600;4800;7200;9600;19200;57600;');
- parity_menu := NewMenu(parity_menu_ID, 'Parity');
- AppendMenu(parity_menu, 'None;Even;Odd');
- DrawMenuBar;
- width := 80 * char_space + scroll_bar_width + 2 * indent;
- height := 25 * line_space + 2 * indent;
- with window_rectangle do
- begin
- top := 50;
- bottom := top + height;
- left := (screenBits.Bounds.right - screenBits.Bounds.left - width) div 2;
- right := left + width;
- end; { with }
- terminal_window := NewWindow(nil, window_rectangle, 'Dumb Terminal Emulation', true, noGrowDocProc, WindowPtr(-1), false, 0);
- SetPort(terminal_window);
- terminal_rectangle := GrafPtr(terminal_window)^.portRect;
- ClipRect(terminal_rectangle);
- InsetRect(terminal_rectangle, indent, indent);
- with terminal_rectangle do
- right := right - scroll_bar_width;
- TextFont(Monaco);
- TextSize(9);
- TextMode(srcCopy);
- xPos := indent;
- yPos := indent + ascent;
- right_limit := terminal_rectangle.right - 1;
- no_of_lines := (terminal_rectangle.bottom - yPos) div line_space + 1;
- bottom_limit := yPos + (no_of_lines - 1) * line_space - 1;
- DrawGrowIcon(terminal_window);
- with GrafPtr(terminal_window)^.PortRect do
- begin
- PenPat(white);
- MoveTo(0, bottom - 15);
- LineTo(right - 16, bottom - 15);
- PenPat(black);
- end; { with }
-
- with GrafPtr(terminal_window)^.portRect do
- SetRect(temp_rectangle, right - 14, bottom - 29, right, bottom - 14); { L T R B }
- break_button := NewControl(terminal_window, temp_rectangle, 'FFFF80019105890F851D8039B871802182018321871186498E418C418401FFFF', true, 0, 0, 0, $AAC0, 0); { break button }
-
- with GrafPtr(terminal_window)^.portRect do
- SetRect(temp_rectangle, right - 14, bottom - 44, right, bottom - 29); { L T R B }
- checked_parity := even_parity_item;
- temp_control := NewControl(terminal_window, temp_rectangle, 'FFFF8001811D816183898D01F1098101A109811DA1018101A101F38187C1FFFF', true, checked_parity, parity_menu_ID, odd_parity_item, $AAC0, 0); { parity button }
- CheckItem(parity_menu, checked_parity, true);
- SetCRefCon(temp_control, LongInt(parity_menu));
- SetCtlAction(temp_control, @ControlActionProcedure);
-
- with GrafPtr(terminal_window)^.portRect do
- SetRect(temp_rectangle, right - 14, bottom - 59, right, bottom - 44); { L T R B }
- checked_baud := baud_300_item;
- temp_control := NewControl(terminal_window, temp_rectangle, 'FFFF800181018101810180018001C023A025904980418081808181018101FFFF', true, checked_baud, baud_menu_ID, baud_57600_item, $AAC0, 0); { baud button }
- CheckItem(baud_menu, checked_baud, true);
- SetCRefCon(temp_control, LongInt(baud_menu));
- SetCtlAction(temp_control, @ControlActionProcedure);
-
- with GrafPtr(terminal_window)^.portRect do
- SetRect(temp_rectangle, right - 14, bottom - 74, right, bottom - 59); { L T R B }
- help_button := NewControl(terminal_window, temp_rectangle, 'FFFF800183C18FF18C31981998199819807981E181818181800181818181FFFF', true, 0, 0, 0, $AAC0, 0); { help button }
-
- MoveTo(xPos, yPos);
- update_region := NewRgn;
- screen_line := '';
- next_flash_time := 0;
- cursor_visible := false;
- InitCursor;
- finished := false;
- end; { InitializeUserInterface }
-
- {--------------------------------------------------------------------------}
-
- procedure InvertCursor;
-
- begin { InvertCursor }
- SetRect(cursor_rectangle, xPos - 1, yPos - 2, xPos + 6, yPos + 1);
- InvertRect(cursor_rectangle);
- cursor_visible := not cursor_visible;
- end; { InvertCursor }
-
- {--------------------------------------------------------------------------}
-
- procedure HideTheCursor;
-
- begin { HideTheCursor }
- if cursor_visible then
- InvertCursor;
- next_flash_time := TickCount + flash_interval;
- end; { HideTheCursor }
-
- {--------------------------------------------------------------------------}
-
- procedure FlashCursor;
- var
- tick_count: LongInt;
-
- begin { FlashCursor }
- tick_count := TickCount;
- if tick_count > next_flash_time then
- begin
- InvertCursor;
- next_flash_time := tick_count + flash_interval;
- end;
- end; { FlashCursor }
-
- {--------------------------------------------------------------------------}
-
- procedure Linefeed;
-
- begin { Linefeed }
- HideTheCursor;
- if yPos > bottom_limit then
- ScrollRect(terminal_rectangle, 0, -line_space, update_region)
- else
- begin
- yPos := yPos + line_space;
- MoveTo(xPos, yPos);
- end;
- end; { Linefeed }
-
- {--------------------------------------------------------------------------}
-
- procedure CarriageReturn;
-
- begin { CarriageReturn }
- HideTheCursor;
- xPos := indent;
- MoveTo(xPos, yPos);
- end; { CarriageReturn }
-
- {--------------------------------------------------------------------------}
-
- procedure HandleMenuChoice;
- var
- which_menu: integer;
- which_item: integer;
-
- curPort: GrafPtr;
- str: Str255;
-
- begin { HandleMenuChoice }
- which_menu := HiWord(menu_choice);
- which_item := LoWord(menu_choice);
- case which_menu of
- appleMenu_ID:
- case which_item of
- about_item:
- if Alert(aboutID, nil) = 1 then
- ;
- otherwise
- begin
- GetPort(curPort);
- GetItem(appleMenu, which_item, str);
- if OpenDeskAcc(str) = 0 then
- ;
- SetPort(curPort);
- end;
- end; { case }
- menu_ID:
- case which_item of
- quit_item:
- finished := true;
- end; { case }
- end; { case }
- HiLiteMenu(0);
- end; { HandleMenuChoice }
-
- {--------------------------------------------------------------------------}
-
- procedure CheckMousePosition;
- var
- stop_time: LongInt;
-
- begin { CheckMousePosition }
- case FindWindow(current_event.where, which_window) of
- inMenuBar:
- begin
- menu_choice := MenuSelect(current_event.where);
- HandleMenuChoice;
- end;
- inDrag:
- begin
- if (which_window <> FrontWindow) and (BitAnd(current_event.modifiers, cmdKey) = 0) then
- SelectWindow(which_window);
- DragWindow(which_window, current_event.where, screenBits.bounds);
- end;
- inContent:
- begin
- click_location := current_event.where;
- GlobalToLocal(click_location);
- if FindControl(click_location, terminal_window, which_control) <> 0 then
- begin
- if TrackControl(which_control, click_location, Ptr(-1)) = 1 then
- begin
- if which_control = break_button then
- begin
- ErrorHandler(SerSetBrk(aOutRefNum));
- Delay(6, stop_time);
- ErrorHandler(SerClrBrk(aOutRefNum));
- end;
- if which_control = help_button then
- if Alert(aboutID, nil) = 1 then
- ;
- end;
- end;
- end;
- otherwise
- begin
- end;
- end; { case }
- end; { CheckMousePosition }
-
- {--------------------------------------------------------------------------}
-
- procedure GetKeyboardChar;
- var
- key: char;
- menu_ID: integer;
- stop_time: LongInt;
-
- begin { GetKeyboardChar }
- with current_event do
- begin
- key := chr((LoWord(message)));{Lo}
- if BitAnd(modifiers, cmdKey) <> 0 then
- begin
- menu_choice := MenuKey(key);
- menu_ID := HiWord(menu_choice);
- Delay(30, stop_time);
- HiLiteMenu(menu_ID);
- HandleMenuChoice;
- end
- else
- begin
- this_char[1] := key;
- byte_count := 1;
- ErrorHandler(FSWrite(AOutRefNum, byte_count, @this_char));
- end;
- end; { with }
- end; { GetKeyboardChar }
-
- {--------------------------------------------------------------------------}
-
- procedure WriteScreenLine;
-
- begin { WriteScreenLine }
- if Length(screen_line) > 0 then
- begin
- HideTheCursor;
- DrawString(screen_line);
- xPos := xPos + Length(screen_line) * char_space;
- if xPos > right_limit then
- begin
- CarriageReturn;
- Linefeed;
- end;
- screen_line[0] := chr(0);
- InvertCursor;
- end;
- end; { WriteScreenLine }
-
- {--------------------------------------------------------------------------}
-
- procedure DoUpdate (anEvent: EventRecord);
- var
- savePort: GrafPtr;
- theWindow: WindowPtr;
- begin {DoUpdate}
- theWindow := WindowPtr(anEvent.message);
-
- GetPort(savePort);
- SetPort(theWindow);
- BeginUpdate(theWindow);
- {Handle update events!}
- {If we had kept all text that has been drawn, we could redraw it!}
-
- {Redraw buttons and the grow icon!}
- DrawGrowIcon(theWindow);
- DrawControls(theWindow);
-
- EndUpdate(theWindow);
- SetPort(savePort);
- end; {DoUpdate}
-
- {--------------------------------------------------------------------------}
-
- procedure CheckEventQueue;
-
- begin { CheckEventQueue }
- SystemTask;
- FlashCursor;
- {Minor flaw: Should use WaitNextEvent if available. /Ingemar}
- if GetNextEvent(everyEvent, current_event) then
- case current_event.what of
- mouseDown:
- CheckMousePosition;
- keyDown, autoKey:
- GetKeyboardChar;
- {Serious flaw: doesn't handle update events! /Ingemar}
- updateEvt:
- DoUpdate(current_event);
- otherwise
- begin
- end;
- end; { case }
- end; { CheckEventQueue }
-
- {--------------------------------------------------------------------------}
-
- begin { Serial }
- InitializeUserInterface;
- InitializeModemPort;
- repeat
- CheckEventQueue;
- FlashCursor;
- ErrorHandler(SerGetBuf(aInRefNum, byte_count));
- if byte_count > 0 then
- begin
- if byte_count > 64 then
- byte_count := 64;
- ErrorHandler(FSRead(aInRefNum, byte_count, @in_buffer));
- limit := byte_count;
- for index := 1 to limit do
- begin
- received_char := in_buffer[index];
- case ord(received_char) of
- control_G:
- begin
- WriteScreenLine;
- SysBeep(0);
- end;
- control_H:
- begin
- WriteScreenLine;
- HideTheCursor;
- xPos := xPos - char_space;
- MoveTo(xPos, yPos);
- DrawChar(' ');
- MoveTo(xPos, yPos);
- end;
- control_J:
- begin
- WriteScreenLine;
- Linefeed;
- end;
- control_M:
- begin
- WriteScreenLine;
- CarriageReturn;
- end;
- $20..$FF:
- begin
- len := ord(screen_line[0]) + 1;
- screen_line[0] := chr(len);
- screen_line[len] := received_char;
- if xPos + len * char_space > right_limit then
- begin
- WriteScreenLine;
- CarriageReturn;
- Linefeed;
- end;
- end;
- otherwise
- begin
- end;
- end; { case }
- end; { for }
- end;
- if Length(screen_line) > 0 then
- WriteScreenLine;
- until finished;
- {RAMSDClose(SPortA);}
- if aInRefNum <> 0 then
- if CloseDriver(aInRefNum) <> noErr then
- ;
- if aOutRefNum <> 0 then
- if CloseDriver(aOutRefNum) <> noErr then
- ;
-
- DisposeWindow(terminal_window);
- end.